package com.wealth.wechat.service;

import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wealth.wechat.entity.WechatConfig;
import com.wealth.wechat.repository.WechatConfigDao;
import com.wealth.wechat.util.JsonParser;
import com.wealth.wechat.util.TrustSSL;

import iaas.utils.CommonUtil;
import iaas.utils.ResultObject;
import net.sf.json.JSONObject;


@Service
public class WechatConfigService{
	
	Logger logger = Logger.getLogger(WechatConfigService.class);
	
	@Autowired
	private WechatConfigDao wechatConfigDao;
	
	//保存或修改微信配置
	public void saveOrUpdateWeChatCfg(WechatConfig config) {
		WechatConfig temp = wechatConfigDao.findOne(config.getId());
		temp.setWxappid(config.getWxappid());
		temp.setWxappsecret(config.getWxappsecret());
		if(config.getId()!=null){
			temp.setWxaccesstoken(null);
			temp.setWxjsapiticket(null);
			temp.setWxtokenstamp(null);
			temp.setWxticketstamp(null);
		}
		wechatConfigDao.save(temp);
	}
	
	//通过企业查询微信配置
	public WechatConfig getWechatConfigByCorpid(Long corpid) {
		return wechatConfigDao.findByCorpid(corpid);
	}
	
	
    /** 
	 *  2015-2-4 add by wayne
	 *  JS-SDK使用权限签名算法  返回 wx.config参数 
	 * */
	@SuppressWarnings({ "finally", "unchecked" })
	public Map<String, Object> getJsApSign(String reurl,Long corpid)throws Exception{
		
		Map<String, Object> map =  new HashMap<String, Object>();
		try {
			//获取getapi_ticket
			Map<String,Object> ticketMap=getapi_ticket(corpid);
			if(ticketMap!=null){
				 //随机字符串
		        String nonce_str = create_nonce_str();
		        //时间戳
		        String timestamp = create_timestamp();
		        String string1;
		        String signature = "";

		        //注意这里参数名必须全部小写，且必须有序
		        string1 = "jsapi_ticket=" + ticketMap.get("ticket").toString() +
		                  "&noncestr=" + nonce_str +
		                  "&timestamp=" + timestamp +
		                  "&url=" + reurl;
		        logger.info("加密参数string1=："+string1);

		        /** 机密算法 */
	            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
	            crypt.reset();
	            crypt.update(string1.getBytes("UTF-8"));
	            signature = byteToHex(crypt.digest());

		        map.put("url", reurl);
		        map.put("jsapi_ticket", ticketMap.get("ticket").toString());
				map.put("nonceStr", nonce_str);
				map.put("timestamp",Long.valueOf(timestamp));
				map.put("signature", signature);
				
			}else{
				map=null;
				logger.info("getJsApSign加密参数string1：获取jsapi_ticket错误");
			 }
			
		} catch (Exception e) {
			logger.info("getJsApSign加密参数string1异常");
		}finally{
			return map;
		}
	}
	/** 2015-2-4 add by wayne   微信jS-SDK   end */

    private String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
    
    /** 2015-2-4 add by wayne   微信jS-SDK   开始 
	 * 生成签名之前必须先了解一下jsapi_ticket，jsapi_ticket是公众号用于调用微信JS接口的临时票据。
	 * 正常情况下，jsapi_ticket的有效期为7200秒，通过access_token来获取。
	 * 由于获取jsapi_ticket的api调用次数非常有限，频繁刷新jsapi_ticket会导致api调用受限，影响自身业务，
	 * 开发者必须在自己的服务全局缓存jsapi_ticket 
	 * 1.参考以下文档获取access_token（有效期7200秒，开发者必须在自己的服务全局缓存access_token）
	 * 2.用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket（有效期7200秒，开发者必须在自己的服务全局缓存jsapi_ticket）
	 * https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
	 * @return
	 */
	private static String api_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
	@SuppressWarnings("finally")
	public JSONObject getapi_ticket(Long corpid)throws Exception{
		
		JSONObject ticketMap= new JSONObject();
		try {
			
			//获取access_token
			Map<String,Object> accessToken=getAccessToken(corpid);
			if(accessToken!=null && accessToken.get("access_token")!=null){
				WechatConfig config = getWechatConfigByCorpid(corpid);
				if (config != null) {
					//数据库中 的jsapi_ticket存在 并且没有超时  获取已经超时7200秒
					if(CommonUtil.isNotNull(config.getWxjsapiticket()) && CommonUtil.isNotNull(config.getWxticketstamp())
						&& ((System.currentTimeMillis()-config.getWxticketstamp())/1000<7200)){
						
						//从数据库中获取jsapi_ticket
						ticketMap.put("ticket", config.getWxjsapiticket());
					}else{
						
						//重新请求 jsapi_ticket
						String url = api_ticket_url.replace("ACCESS_TOKEN", accessToken.get("access_token").toString());
						String jsonStr = TrustSSL.sendNewRequest(url, null);

						logger.info("采用http GET方式请求获得jsapi_ticket="+jsonStr);
						ticketMap=JSONObject.fromObject(jsonStr);
						
						/*2015-2-4  add by wayne 数据库缓存jsapi_ticket */
						if(ticketMap !=null && ticketMap.get("ticket")!=null){
							config.setWxjsapiticket(ticketMap.get("ticket").toString());
							config.setWxticketstamp(System.currentTimeMillis());
							//update
							wechatConfigDao.save(config);
							
							ticketMap.put("status", "1");
						}else{
							logger.info("getapi_ticket获取ticket:失败！！");
							ticketMap=null;
						}
					}
					
				}else{
					logger.info("getapi_ticket获取tcorp失败！！");
					ticketMap=null;
				}
			}else{
				logger.info("getapi_ticket获取access_token:失败！！");
				ticketMap=null;
			}
			
		} catch (Exception e) {
			ticketMap=null;
		}finally{
			return ticketMap;
		}
	}
    
    
	/**
	 获取网页授权access_token
	 { 
	 "access_token":"ACCESS_TOKEN",    
	 "expires_in":7200,    
	 "refresh_token":"REFRESH_TOKEN",    
	 "openid":"OPENID",    
	 "scope":"SCOPE" 
	 } 
	 */
	private static String token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
	public com.alibaba.fastjson.JSONObject getAccessToken(String appid,String secret,String code) throws Exception{
		try {
			String url = token_url.replace("CODE", code);
			url = url.replace("APPID", appid);
			url = url.replace("SECRET", secret);
			
			String str = TrustSSL.sendNewRequest(url, null); 
			logger.info("-->获取网页授权access_token="+str);
			
			return com.alibaba.fastjson.JSONObject.parseObject(str);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	    拉取用户信息
		{    
		 "openid":" OPENID",  
		 " nickname": NICKNAME,   
		 "sex":"1",   
		 "province":"PROVINCE"   
		 "city":"CITY",   
		 "country":"COUNTRY",    
		 "headimgurl":    "http://wx.qlogo.cn/mmopen/g3Mon46",  
		"privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],    
		 "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" 
		} 
	 */
	private static String userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
	public com.alibaba.fastjson.JSONObject  getUserInfo(String accessToken,String openid)throws Exception{
		try {
			String url = userinfo_url.replace("ACCESS_TOKEN", accessToken);
			url = url.replace("OPENID", openid);
			
			String str = TrustSSL.sendNewRequest(url, null);
			logger.info("-->获取用户信息="+str);
			
			return com.alibaba.fastjson.JSONObject.parseObject(str);
		} catch (Exception e) {
			return null;
		}
	}
	
//	/**
//	 * 网页授权获取用户的基本信息
//	 * @param accessToken
//	 * @param openid
//	 * @return
//	 */
//	private static String userinfo_url2 = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
//	@SuppressWarnings("finally")
//	public JSONObject getUserInfo2(String accessToken,String openid)throws Exception{
//		
//		JSONObject userMap= new JSONObject();
//		try {
//			
//			String url = userinfo_url2.replace("ACCESS_TOKEN", accessToken);
//			url = url.replace("OPENID", openid);
//
//			String jsonStr = TrustSSL.sendNewRequest(url, null);
//			//logger.info("用户同意授权url="+url);
//			logger.info("用户同意授权2jsonStr="+jsonStr);
//			userMap=JSONObject.fromObject(jsonStr);
//		} catch (Exception e) {
//			userMap = null;
//		}finally{
//			return userMap;
//		}
//	}
//	
//	
//	/**
//	 * 不需求用户网页授权  直接获取用户的基本信息图像和昵称
//	 * @param accessToken
//	 * @param openid
//	 * @return
//	 */
//	@SuppressWarnings("finally")
//	public JSONObject getUserInfo(String openid,Long corpid)throws Exception{
//		JSONObject userMap= new JSONObject();
//		try {
//			//获取access_token
//			Map<String,Object> atMap=getAccessToken(corpid);
//			if(atMap==null || CommonUtil.isNull (atMap.get("access_token"))){
//				logger.info("getUserInfo获取用户的基本信息图像和昵称: 获取access_token失败");
//				return userMap;
//			}
//			
//			String url = userinfo_url2.replace("ACCESS_TOKEN", String.valueOf(atMap.get("access_token")));
//			url = url.replace("OPENID", openid);
//	
//			String jsonStr = TrustSSL.sendNewRequest(url, null);
//			//logger.info("用户同意授权url="+url);
//			logger.info("用户同意授权jsonStr="+jsonStr);
//			userMap = JSONObject.fromObject(jsonStr);
//		
//		} catch (Exception e) {
//			userMap = null;
//		}finally{
//			return userMap;
//		}
//	}
	
	/**
	 * 再次  获取access_token  拉取用户昵称和图像   不需打开授权页面
	 * 在确保微信公众账号拥有授权作用域（scope参数）的权限的前提下（服务号获得高级接口后，
	 * 默认拥有scope参数中的snsapi_base和snsapi_userinfo），引导关注者打开授权页面
	 * @return
	 */
	@SuppressWarnings("finally")
	public  Map<String, Object> getAccessToken(Long corpid)throws Exception{
		 
			Map<String, Object> tokenMap= new HashMap<String, Object>();
			try {
				WechatConfig config = getWechatConfigByCorpid(corpid);
				if (config != null) {
					
					//数据库中 的access_token存在 并且没有超时  获取已经超时7200秒
					if(CommonUtil.isNotNull(config.getWxaccesstoken()) && CommonUtil.isNotNull(config.getWxtokenstamp())
						&& ((System.currentTimeMillis()-config.getWxtokenstamp())/1000<7200)){
						
						//从数据库中获取access_token
						tokenMap.put("access_token", config.getWxaccesstoken());
						
					}else{
						//重新请求 access_token
						String appid = config.getWxappid();
						String appsecret=config.getWxappsecret();
						
						String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";
						url = url.replace("{appid}", appid).replace("{secret}", appsecret);
						String requestMsg="获取access_token:";
						
						String jsonStr = TrustSSL.sendRequest(url, requestMsg);
						tokenMap = JsonParser.json2Map(jsonStr);
						
						
						/*2015-2-4  add by wayne 数据库缓存access_token */
						if(tokenMap !=null && tokenMap.get("access_token")!=null){
							config.setWxaccesstoken(tokenMap.get("access_token").toString());
							config.setWxtokenstamp(System.currentTimeMillis());
							
							wechatConfigDao.save(config);
						}else{
							logger.error("getAccessToken获取access_token:失败！！jsonStr="+jsonStr);
						}
						
					}
					
				} else {
					logger.error("公众号未设置APPID和APPSECRET!");
					return null;
				}
				
			} catch (Exception e) {
				tokenMap = null;
			}finally{
				return tokenMap;
			}
	}

}
